/*
 *    Copyright © OpenAtom Foundation.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

package com.inspur.edp.bef.engine.common;

import com.inspur.edp.bef.api.be.IBEManagerContext;
import com.inspur.edp.bef.core.be.BENodeEntity;
import com.inspur.edp.bef.engine.BefEngineException;
import com.inspur.edp.bef.api.lcp.ILcpFactory;
import com.inspur.edp.bef.api.lcp.IStandardLcp;
import com.inspur.edp.bef.api.parameter.retrieve.RetrieveParam;
import com.inspur.edp.bef.bizentity.GspBizEntityElement;
import com.inspur.edp.bef.bizentity.GspBizEntityObject;
import com.inspur.edp.bef.bizentity.GspBusinessEntity;
import com.inspur.edp.bef.bizentity.beenum.BETriggerTimePointType;
import com.inspur.edp.bef.bizentity.beenum.RequestNodeTriggerType;
import com.inspur.edp.bef.bizentity.common.BefDtBeanUtil;
import com.inspur.edp.bef.bizentity.operation.BizAction;
import com.inspur.edp.bef.bizentity.operation.BizMgrAction;
import com.inspur.edp.bef.bizentity.operation.BizOperation;
import com.inspur.edp.bef.bizentity.operation.internalmgraction.TccSettingElement;
import com.inspur.edp.bef.component.base.GspComponent;
import com.inspur.edp.bef.engine.core.be.EngineBusinessEntity;
import com.inspur.edp.bef.engine.core.be.EngineChildEntity;
import com.inspur.edp.bef.engine.entity.AssociationInfo;
import com.inspur.edp.bef.engine.entity.EngineChildAccessor;
import com.inspur.edp.bef.engine.entity.EngineRootAccessor;
import com.inspur.edp.bef.spi.action.AbstractManagerAction;
import com.inspur.edp.cdf.component.api.service.ComponentInvokeService;
import com.inspur.edp.cef.api.dataType.entity.ICefEntityContext;
import com.inspur.edp.cef.designtime.api.IGspCommonField;
import com.inspur.edp.cef.designtime.api.collection.GspFieldCollection;
import com.inspur.edp.cef.designtime.api.element.ElementDefaultVauleType;
import com.inspur.edp.cef.designtime.api.element.GspAssociation;
import com.inspur.edp.cef.designtime.api.element.GspElementDataType;
import com.inspur.edp.cef.designtime.api.element.GspElementObjectType;
import com.inspur.edp.cef.designtime.api.element.GspEnumValue;
import com.inspur.edp.cef.designtime.api.util.MetadataUtil;
import com.inspur.edp.cef.entity.condition.EntityFilter;
import com.inspur.edp.cef.entity.condition.FieldsFilter;
import com.inspur.edp.cef.entity.condition.RetrieveFilter;
import com.inspur.edp.cef.entity.entity.ICefData;
import com.inspur.edp.cef.entity.entity.IEntityData;
import com.inspur.edp.cef.entity.entity.IValuesContainer;
import com.inspur.edp.cef.entity.entity.dynamicProp.DynamicPropSetImpl;
import com.inspur.edp.cef.spi.common.UdtManagerUtil;
import com.inspur.edp.cef.spi.entity.resourceInfo.builinImpls.CefEntityResInfoImpl;
import com.inspur.edp.cef.spi.entityaction.CefDataTypeAction;
import com.inspur.edp.cef.spi.util.ExpressionUtil;
import com.inspur.edp.commonmodel.engine.api.common.CMEngineUtil;
import com.inspur.edp.commonmodel.engine.core.common.CMUtil;
import com.inspur.edp.das.commonmodel.IElementCollection;
import com.inspur.edp.das.commonmodel.IGspCommonElement;
import com.inspur.edp.das.commonmodel.IGspCommonObject;
import com.inspur.edp.lcm.metadata.api.entity.GspMetadata;
import com.inspur.edp.metadata.rtcustomization.api.CustomizationRtService;
import com.inspur.edp.svc.expression.api.IExpressionEvaluator;
import com.inspur.edp.udt.designtime.api.entity.ComplexDataTypeDef;
import com.inspur.edp.udt.designtime.api.entity.SimpleDataTypeDef;
import com.inspur.edp.udt.designtime.api.entity.UnifiedDataTypeDef;
import com.inspur.edp.udt.entity.IUdtData;
import io.iec.edp.caf.boot.context.CAFContext;
import io.iec.edp.caf.common.JSONSerializer;
import io.iec.edp.caf.commons.utils.SpringBeanUtils;

import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.math.BigDecimal;
import java.sql.Date;
import java.time.OffsetDateTime;
import java.util.*;
import java.util.function.Predicate;
import java.util.stream.Collectors;

import org.apache.commons.lang3.time.FastDateFormat;
import org.apache.http.entity.SerializableEntity;
import org.springframework.util.StringUtils;

public class GspBizEntityUtil extends CMUtil {
    private static ComponentInvokeService componentInvokeService = SpringBeanUtils.getBean(ComponentInvokeService.class);
  public static AbstractManagerAction instantiateMgrAction(
      GspBusinessEntity be, String actionCode, IBEManagerContext context, Object... pars) {
    Objects.requireNonNull(actionCode, "actionCode");
    Objects.requireNonNull(be, "be");

    BizMgrAction op =
        (BizMgrAction)
            be.getBizMgrActions().stream()
                .filter(item -> item.getCode().equals(actionCode))
                .findFirst()
                .orElse(null);
    if (op == null) {
      throwMgrActionNotFound(be, actionCode);
    }
    return instantiateBEMgrOperation(be, op, AbstractManagerAction.class, context, pars);
  }
  public static CefDataTypeAction instantiateBizAction(
      GspBizEntityObject note, String actionCode, ICefEntityContext context, Object... pars){
      Objects.requireNonNull(actionCode, "actionCode");
      Objects.requireNonNull(note, "note");
      BizAction op = null;

//      GspBizEntityObject obj = be.getAllNodes().stream().filter(
//          item-> item.getCode().equals(context.getCode())
//      ).findFirst().orElse(null);
//      if(obj == null)
//        throwMgrActionNotFound(be, actionCode);
      op = (BizAction)note.getBizActions().stream().filter(
          item-> item.getCode().equals(actionCode)
      ).findFirst().orElse(null);
    if (op == null)
      throwBizActionNotFound(note,actionCode);
    return instantiateBEBizOperation(op, CefDataTypeAction.class, context, pars);
  }

  public static <T> T instantiateBEMgrOperation(
          GspBusinessEntity be,  BizOperation op, Class<T> clazz, IBEManagerContext context, Object... pars) {
    CustomizationRtService mdService = BefDtBeanUtil.getCustomizationRtService();
    GspComponent metadata = CMEngineUtil.getMetadataContent(op.getComponentId());
    if (metadata == null) {
      throwBizOperationCompNotFound(op);
    }
    String typeName = metadata.getMethod().getClassName();
    try {
      if(BizOperationUtil.isBuildInAction(op.getComponentId())){
        return (T)BizOperationUtil.getInstance(be, op, context, metadata, pars);
      } else {
        Object[] args = new Object[pars != null ? pars.length + 1 : 1];
        args[0] = context;
        if (pars != null) {
          System.arraycopy(pars, 0, args, 1, pars.length);
        }
          return getComponentClass(op.getComponentId(), Arrays.asList(args));
//        Constructor constructor = Arrays.stream(Class.forName(typeName).getConstructors())
//            .filter(ctor -> ctor.getParameterCount() == args.length).findFirst().orElse(null);
//        if(constructor== null){
//          throw new RuntimeException("构件类[" + typeName + "]上找不到"+args.length+"个参数的构造函数, 请传入匹配的参数");
//        }
//        return (T) constructor.newInstance(args);
      }
    } catch (Exception var2) {
      throw new BefEngineException(var2);
    }
  }

  private static <T> T instantiateBEBizOperation(
    BizOperation op, Class<T> clazz, ICefEntityContext context, Object... pars) {
      //    GspComponent metadata = CMEngineUtil.getMetadataContent(op.getComponentId());
//    if (metadata == null ) {
//      throwBizOperationCompNotFound(op);
//    }
//    String typeName = metadata.getMethod().getClassName();

      Object[] args = new Object[pars != null ? pars.length + 1 : 1];
      args[0] = context;
      if (pars != null) {
          System.arraycopy(pars, 0, args, 1, pars.length);
      }
      return (T) componentInvokeService.getInstance(op.getComponentId(), Arrays.asList(args));

//    Constructor constructor = null;
//    try {
//      constructor = Class.forName(typeName).getConstructors()[0];
//    } catch (ClassNotFoundException e) {
//      e.printStackTrace();
//    }
//    try {
//      return (T) constructor.newInstance(args);
//    } catch (InstantiationException | IllegalAccessException |InvocationTargetException var2) {
//      throw new RuntimeException(var2);
//    }
}

  public static Constructor getConstructor(String compId, Class... parTypes) {
    GspComponent beComponent = CMEngineUtil.getMetadataContent(compId);
    try {
      Class clazz = Class.forName(beComponent.getMethod().getClassName());
      return clazz.getConstructor(parTypes);
    } catch (ClassNotFoundException | NoSuchMethodException e) {
      throw new BefEngineException(e);
    }
  }

    /**
     * @param compId 构件ID
     * @param constructorArgs 构造函数参数
     * @param <T> 返回值类型
     * @return 构件类
     */
    public static <T> T getComponentClass(String compId, List<Object> constructorArgs) {
        return (T) componentInvokeService.getInstance(compId, constructorArgs);
    }

    public static boolean equals(IGspCommonElement element, Object value1, Object value2) {
    if (element.getMDataType() == GspElementDataType.Binary && value1 != null
        && value1 instanceof byte[] && value2 != null && value2 instanceof byte[]) {
      return Arrays.equals((byte[]) value1, (byte[]) value2);
    }
    if (value1 == null) {
      return value2 == null;
    }
    return value1.equals(value2);
  }

  public static boolean canTrigger(Map<BETriggerTimePointType, EnumSet<RequestNodeTriggerType>> tiggerPoints, BETriggerTimePointType tiggerPoint) {
    EnumSet<RequestNodeTriggerType> requestNodeTriggerTypes = tiggerPoints.get(tiggerPoint);
    return requestNodeTriggerTypes != null && !requestNodeTriggerTypes.isEmpty();
  }

  public static void throwElementNotFound(IGspCommonObject node, String labelId) {
    throw new BefEngineException("找不到字段" + node.getCode() + "." + labelId, null);
  }

  public static void throwMgrActionNotFound(GspBusinessEntity be, String actionCode) {
    throw new BefEngineException("找不到be自定义动作" + be.getCode() + "." + actionCode, null);
  }

  public static void throwBizActionNotFound(GspBizEntityObject note, String actionCode) {
    throw new BefEngineException("找不到be实体动作" + note.getCode()+ "." + actionCode);
  }

  public static void throwBizOperationCompNotFound(BizOperation op) {
    throw new BefEngineException("动作对应的构件元数据不存在" + op.getCode() + "." + op.getComponentName());
  }

  public static void throwNoTccComp(GspBizEntityObject node, TccSettingElement setting) {
    throw new BefEngineException(String.format("业务实体[%s]上的节点[%s]的tcc配置[%s]没有设置对应的构件，请正确设置构件",
        node.getBelongModel().getCode(),
        node.getCode(),
        setting.getCode()));
  }

  public static String getString(boolean isDefaultNull) {
        if (isDefaultNull)
            return null;
        return "";
    }
    public static Integer getInteger(boolean isDefaultNull) {
        if (isDefaultNull)
            return null;
        return Integer.valueOf(0);
    }
    public static BigDecimal getDecimal(boolean isDefaultNull) {
        if (isDefaultNull)
            return null;
        return new BigDecimal("0.0");
    }
    public static Boolean getBoolean(boolean isDefaultNull) {
        if (isDefaultNull)
            return null;
        return Boolean.valueOf(false);
    }

    public static void initBasicType(IGspCommonField element, IEntityData data, boolean isDefaultNull) {
        switch (element.getMDataType()) {
            case String:
            case Text:
                data.setValue(element.getLabelID(), getString(isDefaultNull));
                break;
            case Integer:
                data.setValue(element.getLabelID(), getInteger(isDefaultNull));
                break;
            case Decimal:
                data.setValue(element.getLabelID(), getDecimal(isDefaultNull));
                break;
            case Boolean:
                data.setValue(element.getLabelID(), getBoolean(isDefaultNull));
                break;
        }
    }

    public static void initBeDataValue(IGspCommonObject node, IEntityData data,
        Predicate<IGspCommonField> predicate, CefEntityResInfoImpl resInfo) {
        for (IGspCommonField field : node.getContainElements()) {
            if (predicate != null && !predicate.test(field)) {
                continue;
            }

            if (node.getIDElement() == field) {
                continue;
            }
            boolean isDefaultNull = ((GspBizEntityElement)field).getIsDefaultNull();
            if (field.getIsUdt()) {
                initUdtValue(field,data,resInfo,isDefaultNull);
                continue;
            }
            switch (field.getObjectType()) {
                case None:
                    initBasicType(field, data, isDefaultNull);
                    break;
                case Enum:
                    initEnumValue(field, data, isDefaultNull);
                    break;
                case DynamicProp:
                    data.setValue(field.getLabelID(), new DynamicPropSetImpl());
                    break;
                case Association:
                    if (field.getObjectType() == GspElementObjectType.Association && field
                        .getChildAssociations() != null &&
                        !field.getChildAssociations().isEmpty()) {
                        data.setValue(field.getLabelID(), new AssociationInfo((GspAssociation)field
                            .getChildAssociations().get(0)));
                    }
                    break;
            }
        }
    }

    private static void initUdtValue(IGspCommonField field, IEntityData data, CefEntityResInfoImpl resInfo,boolean isDefaultNull) {
        String udtId = field.getUdtID();
        UnifiedDataTypeDef udtContent = (UnifiedDataTypeDef) getMetaData(udtId).getContent();
        String udtConfigId = getUdtConfigId(field, resInfo);
        if (udtContent instanceof ComplexDataTypeDef){
            data.setValue(field.getLabelID(), UdtManagerUtil.getUdtFactory().createManager(udtConfigId).createDataType());
            return;
        }
        if (udtContent instanceof SimpleDataTypeDef){
            initSimpleUdt(field,data,isDefaultNull,udtConfigId);
        }
    }

    private static void initSimpleUdt(IGspCommonField field, IEntityData data, boolean isDefaultNull,String udtConfigId) {
        switch (field.getObjectType()){
            case None:
                initUdtBaicValue(field,data,isDefaultNull,udtConfigId);
                break;
            case Enum:
                initUdtEnumValue(field,data,isDefaultNull,udtConfigId);
                break;
            case Association:
                data.setValue(field.getLabelID(), UdtManagerUtil.createData(udtConfigId));
                break;
            case DynamicProp:
                data.setValue(field.getLabelID(), UdtManagerUtil.createData(udtConfigId));
                break;
            default:
                throw new BefEngineException("不支持的数据对象类型："+field.getObjectType());
        }
    }

    private static void initUdtEnumValue(IGspCommonField field, IEntityData data, boolean isDefaultNull, String udtConfigId) {
        data.setValue(field.getLabelID(),isDefaultNull?UdtManagerUtil.createData(udtConfigId,null):UdtManagerUtil.createData(udtConfigId));
    }

    private static void initUdtBaicValue(IGspCommonField field, IEntityData data, boolean isDefaultNull, String udtConfigId) {
        switch (field.getMDataType()){
            case String:
                data.setValue(field.getLabelID(),isDefaultNull?UdtManagerUtil.createData(udtConfigId):UdtManagerUtil.createData(udtConfigId,getString(isDefaultNull)));
                break;
            case Text:
                data.setValue(field.getLabelID(),isDefaultNull?UdtManagerUtil.createData(udtConfigId):UdtManagerUtil.createData(udtConfigId,getString(isDefaultNull)));
                break;
            case Integer:
                data.setValue(field.getLabelID(),isDefaultNull?UdtManagerUtil.createData(udtConfigId):UdtManagerUtil.createData(udtConfigId,getInteger(isDefaultNull)));
                break;
            case Decimal:
                data.setValue(field.getLabelID(),isDefaultNull?UdtManagerUtil.createData(udtConfigId):UdtManagerUtil.createData(udtConfigId,getDecimal(isDefaultNull)));
                break;
            case Boolean:
                data.setValue(field.getLabelID(),isDefaultNull?UdtManagerUtil.createData(udtConfigId):UdtManagerUtil.createData(udtConfigId,getBoolean(isDefaultNull)));
                break;
            case Date:
                data.setValue(field.getLabelID(), UdtManagerUtil.createData(udtConfigId));
                break;
            case DateTime:
                data.setValue(field.getLabelID(), UdtManagerUtil.createData(udtConfigId));
                break;
            case Binary:
                data.setValue(field.getLabelID(), UdtManagerUtil.createData(udtConfigId));
                break;
            default:
                throw new BefEngineException("不支持的字段数据类型："+field.getMDataType());
        }
    }

    private static  GspMetadata  getMetaData(String metaId){
        GspMetadata udtMetadata;
        try {
            udtMetadata = MetadataUtil.getCustomRTMetadata(metaId);
        } catch (Exception var4) {
            throw new BefEngineException("获取Udt元数据失败，元数据ID为：" + metaId, var4);
        }
        return udtMetadata;
    }
    public static void initEnumValue(IGspCommonField element, IEntityData data, boolean isDefaultNull) {
    if (isDefaultNull) {
      data.setValue(element.getLabelID(), null);
    } else {
      GspEnumValue defaultValue = element.getContainEnumValues().stream()
          .filter(item -> item.getIsDefaultEnum()).findFirst()
          .orElse(element.getContainEnumValues().get(0));
      data.setValue(element.getLabelID(), defaultValue.getValue());
    }
  }

    /**
     * 默认值
     *
     * @param node 实体节点
     * @param data 数据data
     */
    public static void assignDefaultValue(GspBizEntityObject node, IEntityData data) {
//        IGspCommonObject node = entity.getMainObject();
        for (IGspCommonField field : node.getContainElements()) {
            if (StringUtils.isEmpty(field.getDefaultValue())) {
                continue;
            }
            try {
                // udt 单独处理
                if (field.getIsUdt()) {
                    dealUdtDefaultValue(field, data);
                    continue;
                }
            } catch (Throwable e) {
                throw new BefEngineException(String
                    .format("ID编号名称分别为[%s][%s][%s]的模型的节点[%s]的字段[%s]上设置的默认值[%s]不存在, 请联系元数据开发人员修改.",
                        node.getBelongModel().getID(), node.getBelongModel().getCode(),
                        node.getBelongModel().getName(), node.getCode(), field.getCode(),
                        field.getDefaultValue()), e);
            }
            try {
                switch (field.getObjectType()) {
                    case Enum:
                        data.setValue(field.getLabelID(), field.getDefaultValue());
                        break;
                    case None:
                        assignDefaultValue_NoneObjType(field, data);
                        break;
                    case Association:
                        assignDefaultValue_AssociationType(field, data);
                    default:
                }
                // TODO: 动态属性初始值
            } catch (Throwable e) {
                if (e instanceof BefEngineException){
                    throw e;
                }
                throw new BefEngineException(String
                    .format("ID编号名称分别为[%s][%s][%s]的模型的节点[%s]的字段[%s]上设置的默认值[%s]格式不正确, 请联系元数据开发人员修改.",
                        node.getBelongModel().getID(), node.getBelongModel().getCode(),
                        node.getBelongModel().getName(), node.getCode(), field.getCode(),
                        field.getDefaultValue()), e);
            }
        }
    }

    public static void assignChildObjectDefaultValue(GspBizEntityObject node, IEntityData data,EngineChildEntity engineChildEntity) {
//        IGspCommonObject node = entity.getMainObject();
        Map<String,String>  expressionValueMap = new HashMap<>(2);
        for (IGspCommonField field : node.getContainElements()) {
            if (StringUtils.isEmpty(field.getDefaultValue())) {
                continue;
            }
            try {
                // udt 单独处理
                if (field.getIsUdt()) {
                    dealUdtDefaultValue(field, data);
                    continue;
                }
            } catch (Throwable e) {
                throw new BefEngineException(String
                        .format("ID编号名称分别为[%s][%s][%s]的模型的节点[%s]的字段[%s]上设置的默认值[%s]不存在, 请联系元数据开发人员修改.",
                                node.getBelongModel().getID(), node.getBelongModel().getCode(),
                                node.getBelongModel().getName(), node.getCode(), field.getCode(),
                                field.getDefaultValue()), e);
            }
            try {
                switch (field.getObjectType()) {
                    case Enum:
                        data.setValue(field.getLabelID(), field.getDefaultValue());
                        break;
                    case None:
                        if (expressionValueMap.size()==0){
                            setEvaluatorMap((BENodeEntity)engineChildEntity.getParent(),expressionValueMap);
                        }
                        assignChildDefaultValue_NoneObjType(field,data,expressionValueMap);
                        break;
                    case Association:
                        assignDefaultValue_AssociationType(field, data);
                    default:
                }
                // TODO: 动态属性初始值
            } catch (Throwable e) {
                throw new BefEngineException(String
                        .format("ID编号名称分别为[%s][%s][%s]的模型的节点[%s]的字段[%s]上设置的默认值[%s]格式不正确, 请联系元数据开发人员修改.",
                                node.getBelongModel().getID(), node.getBelongModel().getCode(),
                                node.getBelongModel().getName(), node.getCode(), field.getCode(),
                                field.getDefaultValue()), e);
            }
        }
    }

    /**
     * 关联默认值
     *
     * @param field 字段
     * @param data 数据data
     */
    private static void assignDefaultValue_AssociationType(IGspCommonField field, IEntityData data) {
        if (field.getChildAssociations() == null || field.getChildAssociations().size() < 1) {
            return;
        }
        // 关联带出默认值 检索 ID
        String associationDefaultValue = getSimplyDefaultValueString(field);
        GspAssociation associationInfo = field.getChildAssociations().get(0);
        String refModelId = associationInfo.getRefModelID();
        GspFieldCollection refFields = associationInfo.getRefElementCollection();
        if (refFields == null || refFields.size() < 1) {
            return;
        }
        RetrieveParam param = getRetrieveParam(associationInfo, refFields);
        IStandardLcp lcp = SpringBeanUtils.getBean(ILcpFactory.class).createLcpByBEId(refModelId);
        IEntityData resultData = lcp.retrieve(associationDefaultValue, param).getData();
        List<IGspCommonField> refBeField = getRefBeFields(associationInfo);
        if (refBeField == null) {
            return;
        }
        Map<String, String> refFieldsLabId = getRefFieldsLabelID(refFields, refBeField);
        AssociationInfo fieldData = (AssociationInfo)data.getValue(field.getLabelID());
        if (resultData == null){
            throw new BefEngineException("字段["+field.getName()+"]默认值["+associationDefaultValue+"]不存在，请修改");
        }
        if (refFieldsLabId == null || refFieldsLabId.size() == 0){
            return;
        }
        for (Map.Entry<String, String> idem : refFieldsLabId.entrySet()) {
            fieldData.setValue(idem.getKey(), resultData.getValue(idem.getValue()));
        }
        for (IGspCommonField iGspCommonField : refBeField) {
            if(iGspCommonField.getObjectType().equals(GspElementObjectType.Association)){
                setChildAssInfo(refFields,iGspCommonField,fieldData,resultData);
            }
        }
        fieldData.setValue(field.getLabelID(), associationDefaultValue);
    }

    /**
     * Udt默认值 目前支持：关联
     *
     * @param field 字段
     * @param data 数据
     */
    private static void dealUdtDefaultValue(IGspCommonField field, IEntityData data) {
        String udtId = field.getUdtID();
        UnifiedDataTypeDef beComponent = CMEngineUtil.getMetadataContent(udtId);
        if (beComponent == null) {
            return;
        }

        if (beComponent instanceof SimpleDataTypeDef) {
            // 单值UDT
            // 关联
            if (((SimpleDataTypeDef) beComponent).getObjectType() == GspElementObjectType.Association) {
                assignDefaultValue_AssociationSimpleUdtObjType(field, data, beComponent);
            }
        } else {
            // 多值UDT
            assignDefaultValue_ComplexUdtObjType(field, data, beComponent);
        }

    }

    /**
     * 多值UDT赋默认值
     *
     * @param field 字段
     * @param data 数据data
     * @param unifiedDataTypeDef udt元数据信息
     */
    private static void assignDefaultValue_ComplexUdtObjType(IGspCommonField field, IEntityData data,
        UnifiedDataTypeDef unifiedDataTypeDef) {

        IGspCommonField udtField = unifiedDataTypeDef.getContainElements().get(0);
        // 默认值,需要进行反序列化
        String defaultValue = getComplexDefaultValueString(field);
        String nameSpace = unifiedDataTypeDef.getApiNamespace().getDefaultNamespace();
        String udtConfigID = getUdtConfigId(unifiedDataTypeDef.getID(), nameSpace);

        IUdtData udtDefaultValue = (IUdtData)UdtManagerUtil.getUdtFactory().createManager(udtConfigID).deserialize(defaultValue);
        List<String> udtPropertyNames = udtDefaultValue.getPropertyNames();
        IUdtData udtData = (IUdtData) data.getValue(field.getLabelID());
        IValuesContainer valuesContainer = (IValuesContainer)udtData;
        for (String fieldName : udtPropertyNames) {
            valuesContainer.setValue(fieldName, udtDefaultValue.getValue(fieldName));
        }
    }

    private static String getComplexDefaultValueString(IGspCommonField field) {
        String defaultValue = field.getDefaultValue();
        if (field.getDefaultValueType() == ElementDefaultVauleType.Expression) {
            Object obj = ExpressionUtil.getExpressionValue(defaultValue);
            if (obj instanceof String) {
                defaultValue = obj.toString();
            }
            throw new BefEngineException("多值UDT表达式异常，请联系管理员！");
        }
        return defaultValue;
    }

    /**
     * 单值UDT关联字段支持默认值
     *
     * @param field 关联字段
     * @param data 数据
     * @param unifiedDataTypeDef  udt信息
     */
    private static void assignDefaultValue_AssociationSimpleUdtObjType(IGspCommonField field, IEntityData data,
        UnifiedDataTypeDef unifiedDataTypeDef) {
        if (field.getChildAssociations() == null || field.getChildAssociations().size() < 1) {
            return;
        }
        IGspCommonField udtField = unifiedDataTypeDef.getContainElements().get(0);
        // 关联带出默认值 检索 ID
        String associationDefaultValue = getSimplyDefaultValueString(field);
        GspAssociation associationInfo = udtField.getChildAssociations().get(0);
        String refModelId = associationInfo.getRefModelID();
        GspFieldCollection refFields = associationInfo.getRefElementCollection();
        if (refFields == null || refFields.size() < 1) {
            return;
        }
        RetrieveParam param = getRetrieveParam(associationInfo, refFields);
        IStandardLcp lcp = SpringBeanUtils.getBean(ILcpFactory.class).createLcpByBEId(refModelId);
        IEntityData resultData = lcp.retrieve(associationDefaultValue, param).getData();
        List<IGspCommonField> udtRefBeField = getRefBeFields(associationInfo);
        if (udtRefBeField == null) {
            return;
        }
        Map<String, String> refFieldsLabId = getRefFieldsLabelID(refFields, udtRefBeField);
        IUdtData udtData = (IUdtData) data.getValue(field.getLabelID());
        IValuesContainer valuesContainer = (IValuesContainer)udtData;
        IValuesContainer udtInfo = (IValuesContainer) valuesContainer.createValue(udtData.getPropertyNames().get(0));
        for (Map.Entry<String, String> idem : refFieldsLabId.entrySet()) {
            udtInfo.setValue(idem.getKey(), resultData.getValue(idem.getValue()));
        }
        udtInfo.setValue(udtData.getPropertyNames().get(0), associationDefaultValue);
        valuesContainer.setValue(udtData.getPropertyNames().get(0), udtInfo);
    }

    /**
     * 关联默认值
     * 支持表达式和默认值
     *
     * @param field 字段
     * @return 默认值
     */
    private static String getSimplyDefaultValueString(IGspCommonField field) {
        String associationDefaultValue = field.getDefaultValue();
        if (field.getDefaultValueType() == ElementDefaultVauleType.Expression) {
            associationDefaultValue = ExpressionUtil.getExpressionValue(associationDefaultValue).toString();
        }
        return associationDefaultValue;
    }

    /**
     * 获取关联模型-》Object的字段列表
     *
     * @param associationInfo 关联信息
     * @return 关联字段列表
     */
    private static List<IGspCommonField> getRefBeFields(GspAssociation associationInfo) {
        GspBusinessEntity refBe = CMEngineUtil.getMetadataContent(associationInfo.getRefModelID());
        if (refBe == null) {
            return null;
        }
        List<IGspCommonObject> refObjects = refBe.getAllObjectList();
        for (IGspCommonObject obj : refObjects) {
            if (associationInfo.getRefObjectID().equals(obj.getID())) {
                return obj.getContainElements();
            }
        }
        return null;
    }

    /**
     * 获取关联带出字段code
     *
     * @param fields 关联带出字段
     * @param udtRefBeField 关联带出BE字段列表
     * @return 关联带出字段code集合
     */
    private static Map<String, String> getRefFieldsLabelID(GspFieldCollection fields,
        List<IGspCommonField> udtRefBeField) {

        Map<String, String> refFieldIdToLabelId = udtRefBeField.stream().collect(Collectors.toMap(IGspCommonField::getID, IGspCommonField::getLabelID));
        Map<String, String> udtFieldIdToRefFieldId = new HashMap<>();
        for (IGspCommonField field : fields) {
            if (refFieldIdToLabelId.containsKey(field.getRefElementId())) {
                udtFieldIdToRefFieldId.put(field.getLabelID(), refFieldIdToLabelId.get(field.getRefElementId()));
            }
        }

        return udtFieldIdToRefFieldId;
    }

    /**
     * 设置关联检索过滤字段
     *
     * @param associationInfo 关联信息
     * @param refFields 关联带出字段信息
     * @return 过滤字段
     */
    private static RetrieveParam getRetrieveParam(GspAssociation associationInfo, GspFieldCollection refFields) {
        RetrieveParam param = new RetrieveParam();
        String aoosObjectCode = associationInfo.getRefObjectCode();
        RetrieveFilter retrieveFilter = new RetrieveFilter();
        retrieveFilter.setOnlyRetrieveSomeChilds(true);
        EntityFilter entityFilter = new EntityFilter();
        FieldsFilter fieldsFilter = new FieldsFilter();
        entityFilter.setFieldsFilter(fieldsFilter);
        refFields.forEach(field -> fieldsFilter.getFilterFields().add(field.getID()));
        retrieveFilter.getNodeFilters().put(aoosObjectCode, entityFilter);
        param.setRetrieveFilter(retrieveFilter);

        return param;
    }


    private static void setChildAssInfo(GspFieldCollection refFields,IGspCommonField iGspCommonField,AssociationInfo fieldData,IEntityData resultData){
        GspFieldCollection refElementCollection = iGspCommonField.getChildAssociations().get(0).getRefElementCollection();
        for (IGspCommonField refField : refFields) {
            IGspCommonField item = refElementCollection.getItem(refField.getRefElementId());
            if (item == null){
              continue;
            }
            Object assElementValue =  resultData.getValue(iGspCommonField.getLabelID());
            if (assElementValue instanceof IValuesContainer){
                fieldData.setValue(refField.getLabelID(),((IValuesContainer)assElementValue).getValue(item.getLabelID()));
            }
           // fieldData.setValue(refField.getLabelID(),assElementValue.getValue(item.getLabelID()));
        }
        }

//    private static Map<String,String>  getExpressionValueMap(EngineChildEntity engineChildEntity){
//        Map<String,String> evaluatorMap =new HashMap<>(2);
//        setEvaluatorMap((BENodeEntity) engineChildEntity.getParent(),evaluatorMap);
//        return evaluatorMap;
//    }

    private static void setEvaluatorMap(BENodeEntity nodeEntity,Map<String,String> evaluatorMap){
        if (!nodeEntity.isRoot()){
            setEvaluatorMap((BENodeEntity)nodeEntity.getParent(),evaluatorMap);
            evaluatorMap.put(nodeEntity.getEntityResInfo().getEntityCode(),JSONSerializer.serialize(nodeEntity.getData()));
        }else
            {
            evaluatorMap.put(((EngineBusinessEntity)nodeEntity).getNodeCode(),JSONSerializer.serialize(nodeEntity.getData()));
        }
    }


}
